//
//  XHTMLParser.m
//  VietNews
//
//  Created by Nguyen .a.Hph on 22/3/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import "XHTMLParser.h"
#import "Element.h"
#import "ElementContainer.h"
#import "CellEntry.h"
#import "GTMHTTPFetcher.h"
#import "VietNewsDetailTableViewController.h"
#import "VietNewsArticleViewController.h"
#import "GDataXMLNode.h"
#import "GDataXMLNode+XHTML.h"
#import "GTMNSString+HTML.h"
#import "XMLUtil.h"
#import "Util.h"
#import "FilteredWebCache.h"
#import "SiteClass.h"

@interface XHTMLParser (Private)
+(NSString *)dataFilePath;
@end
@implementation XHTMLParser

+(NSString *) dataFilePath{
    return [[NSBundle mainBundle] pathForResource:@"data" ofType:@"xml"];
}

+(ElementContainer *)loadElementContainer{
    NSString *filePath = [self dataFilePath];
    NSData *xmlData = [[NSMutableData alloc]initWithContentsOfFile:filePath];
    NSError *error;
    GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];
    if (doc==nil) return nil;
    //NSLog(@"%@",doc.rootElement);
    ElementContainer *elementContainer = [[ElementContainer alloc]init];
    NSArray *elementArr = [doc.rootElement elementsForName:@"element"];
    for (GDataXMLElement *ele in elementArr){
        @try{
            NSString *title,*name,*image,*url,*sec,*sec_next,*art,*art_title,*art_url,*art_time,*art_image,*art_desc;
            NSString *art_detail;
            BOOL isMobile;
            int elementID = 0;
            elementID   = [[[ele attributeForName:@"id"] stringValue] intValue];
            title       = [[ele attributeForName:@"title"] stringValue];
            name        = [[ele attributeForName:@"name"] stringValue];
            image       = [[ele attributeForName:@"image"] stringValue];
            isMobile    = [[[ele attributeForName:@"isMobile"] stringValue] boolValue];
            url         = [[[ele elementsForName:@"url"] objectAtIndex:0] stringValue];
            sec         = [[[ele elementsForName:@"sec"] objectAtIndex:0] stringValue];
            sec_next    = [[[ele elementsForName:@"sec_next"] objectAtIndex:0] stringValue];
            art         = [[[ele elementsForName:@"art"] objectAtIndex:0] stringValue];
            art_title   = [[[ele elementsForName:@"art_title"] objectAtIndex:0] stringValue];
            
            NSArray *arrUrl = [ele elementsForName:@"art_url"];
            if ([arrUrl count]>0)
                art_url = [[arrUrl objectAtIndex:0] stringValue];
            
            art_time   = [[[ele elementsForName:@"art_time"] objectAtIndex:0] stringValue];
            art_image   = [[[ele elementsForName:@"art_img"] objectAtIndex:0] stringValue];
            art_desc    = [[[ele elementsForName:@"art_desc"] objectAtIndex:0] stringValue];
            art_detail  = [[[ele elementsForName:@"art_detail"] objectAtIndex:0] XMLString];
            Element *element = [[Element alloc] initWithID:elementID title:title name:name image:image isMobile:isMobile url:url sec:sec sec_next:sec_next art:art art_title:art_title art_url:art_url art_time:art_time art_image:art_image art_desc:art_desc art_detail:art_detail];
            [elementContainer.elements addObject:element];
        }
        @catch (NSException *ex) {
            NSLog(@"%s: %@",__FUNCTION__, ex);
            continue;
        }
    }
    return elementContainer;
}

+(void)getSectionsBySite:(Element *)site tableVC:(UITableViewController *)tableVC{
    VietNewsDetailTableViewController *objTableVC = (VietNewsDetailTableViewController *)tableVC;
    
    //check if sections existed in the NSUserDefaults
    //NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];
    //ElementContainer *elementContainer = [settings objectForKey:@"ElementContainer"];
    //if (elementContainer elements
    
    GTMHTTPFetcher* myFetcher = [self createGTMHTTPFetcherWithUrl:site.url parentUrl:site.url isMobile:site.isMobile];
    [myFetcher beginFetchWithCompletionHandler:^(NSData *retrievedData, NSError *error) {
        if (error != nil) {
            // status code or network error
            NSLog(@"%s: %@",__FUNCTION__, error);
            [Util displayMessage:[NSString stringWithFormat:@"Error code: %d\n%@",[error code], [[error userInfo] valueForKey:@"NSLocalizedDescription"]] withTitle:nil];
        } else {
            // succeeded
            
            NSError *xmlError;
            NSMutableArray *arrItem = [[NSMutableArray alloc] init];
            GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithHTMLData:retrievedData options:0 error:&xmlError];
            if (xmlError){
                NSLog(@"%@", xmlError);
            }
            if (doc==nil) return;
            NSArray *arr = [doc nodesForXPath:site.sec error:&xmlError];
            //NSLog(@"%@", arr);
            
            for (GDataXMLElement *node in arr){
                NSString *title = [[node stringValue] trimWhitespace];
                if ([title length]==0)
                    title = @"Home";
                NSString *node_url = [[node attributeForName:@"href"] stringValue];
                node_url = [Util getAbsoluteUrl:node_url parentUrl:site.url];
                CellEntry *cell = [[CellEntry alloc] initWithTitle:title url:node_url];
                [arrItem addObject:cell];
            }
            
            dispatch_async(dispatch_get_main_queue(), ^{
                [objTableVC didReceiveRemoteData:arrItem from:nil];
            });
        }
    }];
}
+(void)getArticlesByUrl:(NSString *)url site:(Element *)site tableVC:(UITableViewController *)tableVC{
    VietNewsDetailTableViewController *objTableVC = (VietNewsDetailTableViewController *)tableVC;
    
    GTMHTTPFetcher* myFetcher = [self createGTMHTTPFetcherWithUrl:url parentUrl:site.url isMobile:site.isMobile];
    
    [myFetcher beginFetchWithCompletionHandler:^(NSData *retrievedData, NSError *error) {
        if (error != nil) {
            NSLog(@"%s: %@",__FUNCTION__, error);
            [Util displayMessage:[NSString stringWithFormat:@"Error code: %d\n%@",[error code], [[error userInfo] valueForKey:@"NSLocalizedDescription"]] withTitle:nil];
        } else {
            // succeeded
            
            NSError *xmlError;
            NSMutableArray *arrItem = [[NSMutableArray alloc] init];
            GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithHTMLData:retrievedData options:0 error:&xmlError];
            if (xmlError){
                NSLog(@"%@", xmlError);
            }
            if (doc==nil) return;
            NSArray *arr = [doc nodesForXPath:site.art error:&xmlError];
            NSLog(@"%d", [arr count]);
            
            for (GDataXMLElement *node in arr){
                //NSLog(@"%@",node);
                NSString *title, *node_url, *desc, *image, *time;
                
                NSArray *arrUrl = [node nodesForXPath:site.art_url error:nil];
                if ([arrUrl count]>0){
                    node_url = [[[arrUrl objectAtIndex:0] attributeForName:@"href"] stringValue];
                    node_url = [Util getAbsoluteUrl:node_url parentUrl:url];
                }
                
                NSArray *arrTitle = [node nodesForXPath:site.art_title error:nil];
                if ([arrTitle count]>0){
                    title = [[arrTitle objectAtIndex:0] stringValue];
                    if ([arrUrl count]==0){
                        node_url = [[[arrTitle objectAtIndex:0] attributeForName:@"href"] stringValue];
                        node_url = [Util getAbsoluteUrl:node_url parentUrl:url];
                    }
                }
                
                NSArray *arrDesc = [node nodesForXPath:site.art_desc error:nil];
                if ([arrDesc count]>0)
                    desc = [[arrDesc objectAtIndex:0] stringValue];
                
                NSArray *arrImage = [node nodesForXPath:site.art_image error:nil];
                if ([arrImage count]>0)
                    image = [[[arrImage objectAtIndex:0] attributeForName:@"src"] stringValue];
                
                NSArray *arrTime = [node nodesForXPath:site.art_time error:nil];
                if ([arrTime count]>0)
                    time = [[arrTime objectAtIndex:0] stringValue];
                
                CellEntry *cell = [[CellEntry alloc] initWithTitle:title desc:desc url:node_url img:image time:time];
                [arrItem addObject:cell];
                 
            }
            NSString *nextSectionUrl = [self getNextSectionUrl:doc site:site];
            if ([nextSectionUrl length]>0){
                nextSectionUrl = [Util getAbsoluteUrl:nextSectionUrl parentUrl:url];
                nextSectionUrl = [nextSectionUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
            }
            
            dispatch_async(dispatch_get_main_queue(), ^{
                [((VietNewsArticleViewController *)objTableVC) setNextSectionUrl:nextSectionUrl];
                [objTableVC didReceiveRemoteData:arrItem from:nil];
            });
        }
    }];
}
+(void)getArticleDetailByUrl:(NSString *)url site:(Element *)site viewController:(UIViewController *)controller{
    GTMHTTPFetcher* myFetcher = [self createGTMHTTPFetcherWithUrl:url parentUrl:site.url isMobile:site.isMobile];
    
    [myFetcher beginFetchWithCompletionHandler:^(NSData *retrievedData, NSError *error) {
        if (error != nil) {
            NSLog(@"%s: %@",__FUNCTION__, error);
            [Util displayMessage:[NSString stringWithFormat:@"Error code: %d\n%@",[error code], [[error userInfo] valueForKey:@"NSLocalizedDescription"]] withTitle:nil];
        } else {
            // succeeded
            NSError *xmlError;
            GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithHTMLData:retrievedData options:0 error:&xmlError];
            if (xmlError){
                NSLog(@"%@", xmlError);
            }
            if (doc==nil) return;
            
            dispatch_async(dispatch_get_main_queue(), ^{
                [self parseArticleDetailBy:doc url:url site:site viewController:controller];
            });
        }
    }];
}
+(void)getArticleDetailByWebView:(NSString *)url site:(Element *)site viewController:(UIViewController *)controller{
    //UIWebView *webViewDetail = (UIWebView *)[controller.view viewWithTag:1000];
    UIWebView *webViewHidden = (UIWebView *)[controller.view viewWithTag:1001];
    
    NSString *html = [webViewHidden stringByEvaluatingJavaScriptFromString:@"document.documentElement.outerHTML"];
    NSError *error;
    GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithHTMLString:html options:0 error:&error];
    if (error)
        NSLog(@"%s: %@",__FUNCTION__, error);
    if (doc==nil)
        return;
    [self parseArticleDetailBy:doc url:url site:site viewController:controller];
    
    //get more content
    Class siteClass = NSClassFromString(site.name);
    [siteClass getPostContent:url site:site viewController:controller];
}

+(void)parseArticleDetailBy:(GDataXMLDocument *)doc url:(NSString *)url site:(Element *)site viewController:(UIViewController *)controller{
    //UIWebView *webViewDetail = (UIWebView *)[controller.view viewWithTag:1000];
    //UIWebView *webViewHidden = (UIWebView *)[controller.view viewWithTag:1001];
    NSString *html;
    @try {
        html = [self getArticleDetails:doc site:site];
    }
    @catch (NSException *exception) {
        NSLog(@"%s: %@",__FUNCTION__,exception);
        html = [[doc rootElement] HTMLString];
    }
    @finally {
        
    }
    NSSet *srcSet = [XMLUtil getDocumentSrc:doc];
    for(NSString *src in srcSet){
        NSString *escapeSrc = [src gtm_stringByEscapingForHTML];
        NSString *srcAbsolute = [Util getAbsoluteUrl:escapeSrc parentUrl:url];
        //NSLog(@"%@ ---- %@",escapeSrc , srcAbsolute);
        NSString *tmpSrc = [NSString stringWithFormat:@"%@%@%@",@"\"",escapeSrc,@"\""];
        NSString *tmpSrcAbsolute = [NSString stringWithFormat:@"%@%@%@",@"\"",srcAbsolute,@"\""];
        html = [html stringByReplacingOccurrencesOfString:tmpSrc withString:tmpSrcAbsolute];
        
        tmpSrc = [NSString stringWithFormat:@"%@%@%@",@"'",escapeSrc,@"'"];
        tmpSrcAbsolute = [NSString stringWithFormat:@"%@%@%@",@"'",srcAbsolute,@"'"];
        html = [html stringByReplacingOccurrencesOfString:tmpSrc withString:tmpSrcAbsolute];
    }
    NSString *siteResources = [self getSiteResources:doc site:site];
    //NSString *zoomStr = @"<meta name=\"viewport\" content=\"width=device-width; initial-scale=1.0; maximum-scale=5.0; user-scalable=1;\">";
    NSString *jsStr = [self getProgramJS];
    html = [NSString stringWithFormat:@"%@%@<div id=\"body\">%@</div>",jsStr,siteResources,html];
    
    NSArray *arrReturn = [[NSArray alloc] initWithObjects:html, [self getDocumentTitle:doc], nil];
    [((LoadingUIViewController *)controller) didReceiveRemoteData:arrReturn from:nil];
}

+(NSString *)getDocumentTitle:(GDataXMLDocument *)doc{
    GDataXMLNode *titleNode = [XMLUtil getContentFor:@"//title" doc:doc];
    if (titleNode!=nil)
        return [titleNode stringValue];
    return @"";
}

+(NSString *)getSiteResources:(GDataXMLDocument *)doc site:(Element *)site{
    @try {
        GDataXMLElement *node = [[GDataXMLElement alloc] initWithXMLString:site.art_detail error:nil];
        NSMutableString *result = [[NSMutableString alloc] init];
        NSString *resources = [[node attributeForName:@"css"] stringValue];
        NSArray *resourceArr = [resources componentsSeparatedByString:@"|"];
        for(NSString *resource in resourceArr){
            NSString *path = [NSString stringWithFormat:@"%@/%@",site.name,resource];
            path = [[NSURL fileURLWithPath:[Util pathForResource:path directory:@"www"]] absoluteString];
            if ([resource rangeOfString:@".css"].location!=NSNotFound)
                path = [NSString stringWithFormat:@"<link type=\"text/css\" href=\"%@\" rel=\"stylesheet\">",path];
            else {
                path = [NSString stringWithFormat:@"<script type=\"text/javascript\" src=\"%@\"></script>",path];
            }
            [result appendString:path];
        }
        return result;
    }
    @catch (NSException *exception) {
        NSLog(@"%s: %@",__FUNCTION__,exception);
    }
    @finally {
    }
    return @"";
}
+(NSString *)getProgramJS{
    NSMutableString *result = [[NSMutableString alloc] init];
    NSArray *jsArr = [[NSArray alloc] initWithObjects:@"jquery.min.js",@"jscustom.js", nil];
    //NSArray *jsArr = [[NSArray alloc] initWithObjects:@"phonegap-1.4.1.js",@"jquery.min.js",@"jscustom.js", nil];
    for(NSString *jsFile in jsArr){
        NSString *path = [[NSURL fileURLWithPath:[Util pathForResource:jsFile directory:@"www"]] absoluteString];
        path = [NSString stringWithFormat:@"<script type=\"text/javascript\" src=\"%@\"></script>",path];
        [result appendString:path];
    }
    return result;
}
+(NSString *)getArticleDetails:(GDataXMLDocument *)doc site:(Element *)site{
    GDataXMLElement *node = [[GDataXMLElement alloc] initWithXMLString:site.art_detail error:nil];
    NSString *xpath1 = [[node attributeForName:@"xpath1"] stringValue];
    BOOL isInclude1 = [[[node attributeForName:@"isInclude1"] stringValue] boolValue];
    BOOL isInner1 = [[[node attributeForName:@"isInner1"] stringValue] boolValue];
    NSString *xpath2 = [[node attributeForName:@"xpath2"] stringValue];
    BOOL isInclude2 = [[[node attributeForName:@"isInclude2"] stringValue] boolValue];
    BOOL isInner2 = [[[node attributeForName:@"isInner2"] stringValue] boolValue];
    int type = [[[node attributeForName:@"type"] stringValue] intValue];
    BOOL isInner = [[[node attributeForName:@"isInner"] stringValue] boolValue];
    NSString *removeXPaths = [[node attributeForName:@"removeXPaths"] stringValue];
    NSMutableArray *removeXPathArr = [[NSMutableArray alloc] init];
    if (![removeXPaths isEqualToString:@""]){
        NSArray *arr = [removeXPaths componentsSeparatedByString:@"|"];
        [removeXPathArr addObjectsFromArray:arr];
    }
    return [XMLUtil getContent:doc xpath1:xpath1 isInclude1:isInclude1 isInner1:isInner1 xpath2:xpath2 isInclude2:isInclude2 isInner2:isInner2 type:type isInner:isInner removeXPath:removeXPathArr] ;
}

+(NSString *)getNextSectionUrl:(GDataXMLDocument *)doc site:(Element *)site{
    if ([site.sec_next length]>0){
        @try {
            NSArray *arr = [doc nodesForXPath:site.sec_next error:nil];
            if ([arr count]>0)
                return [[arr objectAtIndex:0] stringValue];
        }
        @catch (NSException *exception) {
            NSLog(@"%s: %@",__FUNCTION__, exception);
        }
        @finally {
        }
        return @"";
    }
    //get next section content
    Class siteClass = NSClassFromString(site.name);
    return [siteClass getNextSectionUrl:doc];
}

+(GTMHTTPFetcher *)createGTMHTTPFetcherWithUrl:(NSString *)url parentUrl:(NSString *)parentUrl isMobile:(BOOL)isMobile{
    NSLog(@"start GTM request");
    url = [Util getAbsoluteUrl:url parentUrl:parentUrl];
    NSURLRequest *request = [self createNSURLRequest:url isMobile:isMobile];
    GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request];
    [myFetcher setRetryEnabled:NO];
    return myFetcher;
}
+(NSMutableURLRequest *)createNSURLRequest:(NSString *)url isMobile:(BOOL)isMobile{
    NSURL *nsURL = [NSURL URLWithString:url];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:nsURL];
    NSString *userAgent = @"Mozilla/5.0 (iPhone; U; CPU OS 4_2_1 like Mac OS X) AppleWebKit/532.9 (KHTML, like Gecko) Version/5.0.3 Mobile/8B5097d Safari/6531.22.7";
    if (!isMobile)
        userAgent = @"Mozilla/5.0 (compatible) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6";
    [request addValue:userAgent forHTTPHeaderField:@"User-Agent"];
    return request;
}

@end
